package com.hup.utils.io.batch.function;

import com.hup.utils.commons.ListUtil;
import com.hup.utils.commons.hardware.HRobotJni;
import com.hup.utils.io.batch.BaseBatch;
import com.hup.utils.io.batch.SimpleBatchResp;
import lombok.extern.log4j.Log4j2;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.ArrayList;

/**
 * 使用start命令打开文件夹,文件,程序,网页;
 *
 * @author hugan
 * @apiNote 关于阻塞死锁问题<pre>
 *     发生死锁的情景:
 *     1.生产环境,执行start taskmgr后在读stream时会死锁(直到任务管理器关闭后恢复)
 *     2.任何环境,直接cmd /c taskmgr,在读stream时会死锁
 *     失败解决方案:
 *     1.在命令添加命令/回显/错误命令
 *     2.去掉start
 *     目前解决方法:
 *     1.skip读取stream
 * </pre>
 * @date 2020/2/23
 * @deprecated 使用 {@link HRobotJni#shellExecuteOpen(String, String, String)}代替
 */
@Log4j2
@Deprecated
public class Start implements BaseBatch<SimpleBatchResp> {

    private final String cmd;

    public Start(String filePath) throws FileNotFoundException {
        cmd = buildCmd(filePath, new StringBuilder()).toString();
    }

    public Start(String[] filePaths) throws FileNotFoundException {
        StringBuilder sb = new StringBuilder();
        for (String filePath : filePaths) {
            buildCmd(filePath, sb);
        }
        cmd = sb.toString();
    }

    /**
     * 用默认浏览器打开网页
     *
     * @param url 地址
     * @apiNote 一般网页时正常打开;本地文件时[file:///G:/....]会丢失url上的入参(真的找不到解决方法);
     * 如果地址存在空格,则需要在外部转码(转成%20)
     * @deprecated 使用Desktop.getDesktop().browse(url)代替
     */
    @Deprecated
    public Start(URL url) {
        cmd = "cmd /c start " + url.toString();
    }

    private StringBuilder buildCmd(String filePath, StringBuilder sb) throws FileNotFoundException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        }
        if (sb.length() == 0) {
            //执行start命令前, 需要打开cmd的, 否则会提示命令不存在
            sb.append("cmd /c ");
        } else {
            //&&和&区别: &&是前面的命令错误后就马上终止执行,&不会终止
            sb.append("&");//多个目标时,某个出错不会影响后面的
        }

        if (file.isDirectory()) {
            //如果是文件夹,直接打开文件夹
            appendStart(sb, filePath);
        } else {
            //如果是可执行文件,则先定位到其父目录,再执行start
            String parent = file.getParent();
            sb.append('(');
            sb.append("cd /d \"").append(parent).append('"');
            sb.append("&&");//定位失败后,不会执行start
            appendStart(sb, filePath);
            sb.append(')');
        }
        return sb;
    }

    private void appendStart(StringBuilder sb, String filePath) {
        sb.append("start \"\" ");//无标题
        sb.append('"');//把路径括起来,处理路径中有空格的情况
        sb.append(filePath);
        sb.append('"');
        //sb.append("1>nul 2>nul");//处理返回流一直阻塞的情况,无效
    }

    @Override
    public String cmd() {
        return cmd;
    }

    @Override
    public String desc() {
        return "打开文件夹,文件,程序";
    }

    @Override
    public boolean skipReadStream() {
        return true;
    }

    @Override
    public SimpleBatchResp parse(ArrayList<String> lstResp) {
        //如果是文件不存在,则构造时,就会抛出异常;
        // 正常执行后都是成功的,返回文本也是null
        if (!ListUtil.nullOrEmpty(lstResp)) {
            log.info("resp={}", lstResp);
        }
        return SimpleBatchResp.success();
    }
}
